#define ZCORE_SOURCE
#include "TextProgress.hpp"

namespace zzz {
TextProgress::TextProgress(const string &_content, int endvalue, int startvalue)
{
  SetContent(_content);
  SetValue(endvalue,startvalue);
  SetAppearance('[', ']', '-', '+',30);
}

void TextProgress::SetValue(int _endvalue, int _startvalue)
{
  startvalue=_startvalue;
  endvalue=_endvalue;
  value=startvalue;
}
void TextProgress::SetAppearance(char _beginchar, char _endchar, char _blankchar, char _fillchar, int _length)
{
  beginchar=_beginchar;
  endchar=_endchar;
  blankchar=_blankchar;
  fillchar=_fillchar;
  length=_length;
}
void TextProgress::SetContent(const string &_content)
{
  content=_content;
}
void TextProgress::ShowProgressBegin()
{
  value=startvalue;
  lastlength=0;
  showContent();
}
void TextProgress::ShowProgress(int _value)
{
  clearLastMsg();
  value=_value;
  showContent();
}
void TextProgress::ShowProgressAutoIncrease()
{
  clearLastMsg();
  value++;
  showContent();
}
void TextProgress::ShowProgressEnd(bool clear)
{
  if (clear)
    clearLastMsg();
  else
    cout<<endl;
}
void TextProgress::clearLastMsg()
{
  for (int i=0; i<lastlength; i++) printf("\b");
  lastlength=0;
}
void TextProgress::showBar()
{
  ostringstream oss;
  oss<<beginchar;
  int filllen=((double)value-startvalue)/(endvalue-startvalue)*length;
  for (int i=0; i<filllen; i++) oss<<fillchar;
  for (int i=filllen; i<length; i++) oss<<blankchar;
  oss<<endchar;
  lastlength+=oss.str().size();
  cout<<oss.str();
}
void TextProgress::showSpin()
{
  static int spinvalue=0;
  const char symbol[]="-\\|/";
  cout<<symbol[spinvalue%4];
  lastlength+=1;
  spinvalue++;
}
void TextProgress::showPercentage()
{
  char msg[1024];
  sprintf(msg, "%.2f%%", ((float)value-startvalue)/(endvalue-startvalue)*100);
  lastlength+=strlen(msg);
  cout<<msg;
}
void TextProgress::showNumber()
{
  char msg[1024];
  sprintf(msg, "%d / %d",value,endvalue);
  lastlength+=strlen(msg);
  cout<<msg;
}
void TextProgress::showContent()
{
  for (zuint i=0; i<content.size(); i++)
  {
    if (content[i]=='%')
    {
      if (i==content.size()-1) break;
      else if (content[i+1]=='b')
        showBar();
      else if (content[i+1]=='s')
        showSpin();
      else if (content[i+1]=='p')
        showPercentage();
      else if (content[i+1]=='n')
        showNumber();
      else if (content[i+1]=='%')
      {
        cout<<'%';
        lastlength++;
      }
      i++;
    }
    else
    {
      cout<<content[i];
      lastlength++;
    }
  }
}

}